package org.xshop.socket;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.xshop.service.ITExpressmanService;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;

@Component
public class SocketServer {
    private final Logger logger = LogManager.getLogger(getClass());
    private ExecutorService executorService = Executors.newSingleThreadExecutor();
    @Autowired
    private ITExpressmanService expressmanService;

    public SocketServer() {
        start();
    }

    public void start() {
        executorService.execute(new Runnable() {
            @Override
            public void run() {
                EventLoopGroup group = new NioEventLoopGroup(2);
                EventLoopGroup worker = new NioEventLoopGroup(4);
                try {
                    ServerBootstrap bootstrap = new ServerBootstrap();
                    bootstrap.group(group, worker).channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 1024).option(ChannelOption.SO_RCVBUF, 1024 * 256)
                    .option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
                    .childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
                    .childHandler(new SocketChannelInitializer() {
                        @Override
                        public ChannelHandler[] getHandler() {
                            return new ChannelHandler[]{new ServerHandler(expressmanService)};
                        }
                    }).childOption(ChannelOption.SO_KEEPALIVE, true);
                    ChannelFuture future = bootstrap.bind(16088).sync();
                    if (future.isSuccess()) {
                        logger.info("SocketServer started.");
                    }
                    future.channel().closeFuture().sync();
                } catch (InterruptedException e) {
                    logger.error("", e);
                } finally {
                    group.shutdownGracefully();
                    worker.shutdownGracefully();
                }
            }
        });
    }
}
